package org.iteam.db;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;

import javax.sql.DataSource;

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.ResultSetHandler;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;

/**
 * @Title: Commmethod.java
 * @Description:公用服务类
 * @author Wangchaoyong
 * @date 下午3:08:50
 * @version V1.0
 */
@SuppressWarnings({ "hiding", "unchecked" })
public class BaseService<T> {
	/**
	 * 查询方法
	 * 
	 * @param sql
	 *            组装好的sql语句
	 * @param obj
	 *            参数
	 * @return 返回集合对象T
	 * @throws SQLException
	 */
	protected List<T> query(String sql, Object... obj) throws SQLException {
		DataSource dataSource = DBService.getDataSource();
		ResultSetHandler<List<T>> h = new BeanListHandler<T>(entityClass);
		QueryRunner run = new QueryRunner(dataSource);
		return run.query(sql.toUpperCase(), h, obj);
	}

	/**
	 * 
	 * @param t
	 *            需要返回的对象(用户自行传入的)
	 * @param sql
	 *            组装好的sql语句
	 * @param obj
	 *            参数
	 * @return 返回集合对象T
	 * @throws SQLException
	 */
	protected <T> List<T> query(Class<T> t, String sql, Object... obj)
			throws SQLException {
		ResultSetHandler<List<T>> h = new BeanListHandler<T>(t);
		DataSource dataSource = DBService.getDataSource();
		QueryRunner run = new QueryRunner(dataSource);
		return run.query(sql.toUpperCase(), h, obj);
	}

	protected <T> List<T> query(Connection conn, Class<T> t, String sql,
			Object... obj) throws SQLException {
		ResultSetHandler<List<T>> h = new BeanListHandler<T>(t);
		QueryRunner run = new QueryRunner();
		return run.query(conn, sql.toUpperCase(), h, obj);
	}

	/**
	 * 查询谋一个值
	 * 
	 * @param sql
	 *            组装好的sql语句
	 * @param obj
	 *            参数
	 * @return 返回参数
	 * @throws SQLException
	 */
	protected Object certain(String sql, Object... obj) throws SQLException {
		ResultSetHandler<Object> h = new ScalarHandler<Object>();
		DataSource dataSource = DBService.getDataSource();
		QueryRunner run = new QueryRunner(dataSource);
		return run.query(sql.toUpperCase(), h, obj);
	}

	protected Object certain(Connection conn, String sql, Object... obj)
			throws SQLException {
		ResultSetHandler<Object> h = new ScalarHandler<Object>();
		QueryRunner run = new QueryRunner();
		return run.query(conn, sql.toUpperCase(), h, obj);
	}

	protected <T> T certain(Class<T> t, Connection conn, String sql,
			Object... obj) throws SQLException {
		ResultSetHandler<T> h = new ScalarHandler<T>();
		QueryRunner run = new QueryRunner();
		return run.query(conn, sql.toUpperCase(), h, obj);
	}

	protected <T> T certain(Class<T> t, String sql, Object... obj)
			throws SQLException {
		ResultSetHandler<T> h = new ScalarHandler<T>();
		DataSource dataSource = DBService.getDataSource();
		QueryRunner run = new QueryRunner(dataSource);
		return run.query(sql.toUpperCase(), h, obj);
	}

	protected long counts(String sql, Object... obj) throws SQLException {
		ResultSetHandler<Object> h = new ScalarHandler<Object>();
		DataSource dataSource = DBService.getDataSource();
		QueryRunner run = new QueryRunner(dataSource);
		return Long.parseLong(run.query(sql.toUpperCase(), h, obj).toString());
	}

	protected long counts(Connection conn, String sql, Object... obj)
			throws SQLException {
		ResultSetHandler<Object> h = new ScalarHandler<Object>();
		QueryRunner run = new QueryRunner();
		return Long.parseLong(run.query(conn, sql.toUpperCase(), h, obj).toString());
	}

	/**
	 * 非查询方法(同时修改多条数据)
	 * 
	 * @param sql
	 *            组装好的sql语句
	 * @param obj
	 *            参数
	 * @return 返回受影响的行数
	 * @throws SQLException
	 */
	protected int updates(String sql, Object... obj) throws SQLException {
		DataSource dataSource = DBService.getDataSource();
		QueryRunner run = new QueryRunner(dataSource);
		return run.update(sql.toUpperCase(), obj);
	}

	/**
	 * 非查询方法(同时修改多条数据) 带事务
	 * 
	 * @param conn
	 *            连接对象
	 * @param sql
	 *            组装好的sql语句
	 * @param obj
	 *            参数
	 * @return 返回受影响的行数
	 * @throws SQLException
	 */
	protected int updates(Connection conn, String sql, Object... obj)
			throws SQLException {
		DataSource dataSource = DBService.getDataSource();
		QueryRunner run = new QueryRunner(dataSource);
		return run.update(conn, sql.toUpperCase(), obj);
	}

	/**
	 * 非查询方法
	 * 
	 * @param sql
	 *            组装好的sql语句
	 * @param obj
	 *            参数
	 * @return 是否执行成功（return 成功 false 失败）
	 * @throws SQLException
	 */
	protected boolean update(String sql, Object... obj) throws SQLException {
		return this.updates(sql, obj) == 1 ? true : false;
	}

	/**
	 * 加入了事务
	 * 
	 * @param conn
	 *            连接对象
	 * @param sql
	 *            组装好的sql语句
	 * @param obj
	 *            参数
	 * @return 是否执行成功（return 成功 false 失败）
	 * @throws SQLException
	 */
	protected boolean update(Connection conn, String sql, Object... obj)
			throws SQLException {
		return this.updates(conn, sql, obj) == 1 ? true : false;
	}

	/**
	 * 查询单条数据
	 * 
	 * @param sql
	 *            组装好的sql语句
	 * @param obj
	 *            参数
	 * @return 查询出的对象
	 * @throws SQLException
	 */
	protected T show(String sql, Object... obj) throws SQLException {
		ResultSetHandler<T> h = new BeanHandler<T>(entityClass);
		DataSource dataSource = DBService.getDataSource();
		QueryRunner run = new QueryRunner(dataSource);
		return run.query(sql.toUpperCase(), h, obj);
	}

	protected T show(Connection conn, String sql, Object... obj)
			throws SQLException {
		ResultSetHandler<T> h = new BeanHandler<T>(entityClass);
		QueryRunner run = new QueryRunner();
		return run.query(conn, sql.toUpperCase(), h, obj);
	}

	/**
	 * 
	 * @param t
	 *            返回的实体类对象（传入的是什么实体类对象，就返回与传入的实体类相同的对象，传入USER 返回USER）
	 * @param sql
	 *            组装好的sql语句
	 * @param obj
	 *            参数
	 * @return 查询出的对象
	 * @throws SQLException
	 */
	protected <T> T show(Class<T> t, String sql, Object... obj)
			throws SQLException {
		ResultSetHandler<T> h = new BeanHandler<T>(t);
		DataSource dataSource = DBService.getDataSource();
		QueryRunner run = new QueryRunner(dataSource);
		return run.query(sql.toUpperCase(), h, obj);
	}

	protected Connection getConnection() throws SQLException {
		return DBService.getDataSource().getConnection();
	}

	protected Connection getConnection(boolean autoCommit) throws SQLException {
		Connection conn = DBService.getDataSource().getConnection();
		conn.setAutoCommit(autoCommit);
		return conn;
	}

	protected void close(Connection conn) throws SQLException {
		if (conn != null) {
			if (!conn.isClosed()) {
				conn.close();
			}
		}
	}

	protected void commit(Connection conn) throws SQLException {
		conn.commit();
		conn.setAutoCommit(true);
		close(conn);
	}

	protected void rollback(Connection conn) throws SQLException {
		conn.rollback();
		conn.setAutoCommit(true);
		close(conn);
	}

	protected <T> T show(Class<T> t, Connection conn, String sql, Object... obj)
			throws SQLException {
		ResultSetHandler<T> h = new BeanHandler<T>(t);
		QueryRunner run = new QueryRunner();
		return run.query(conn, sql.toUpperCase(), h, obj);
	}

	public BaseService() {
		// TODO Auto-generated constructor stub
	}

	public BaseService(Class<T> entityClass) {
		this.entityClass = entityClass;
		// TODO Auto-generated constructor stub
	}

	// 程序运行时，当前类将作为基类被继承，通过反射工具类getGenericClassTpye，得到此时泛型 所指定的实际型参数类型
	protected Class<T> entityClass = getGenericClassTpye(this.getClass());

	@SuppressWarnings("rawtypes")
	private static Class getGenericClassTpye(Class clazz) {
		// 得到泛型父类,包含泛型参数信息,如:Class<User>
		Type genericClassType = clazz.getGenericSuperclass();
		// 所有泛型必须实现ParameterizedType接口，如没实现则不是泛型，直接返回Object.class
		if (!(genericClassType instanceof ParameterizedType)) {
			return Object.class;
		}
		// 得到泛型实际参数中对应的Class,如Class<User>中的User,参数可为多个，所以定义为数组
		Type params[] = ((ParameterizedType) genericClassType)
				.getActualTypeArguments();
		if (!(params.length > 0 && params != null)) {
			return Object.class;
		}
		if (!(params[0] instanceof Class)) {
			return Object.class;
		}
		return (Class) params[0];

	}
}
